<?php

namespace Library\Db;

class QueryProvider {

	private $_db;
	private static $_instance;
	
	public static function getProvider() {
		if( self::$_instance === null ) {
			self::$_instance = new self( \Library\Database::getDb() );
		}
		return self::$_instance;
	}
	
	public function __construct( $db ) {
		$this->_db = $db;
	}
	
	public function get( $select, $table, $indexes, $order = null, $start = null, $n = null ) {
	
		$query = 'SELECT ' . $select . ' FROM `' . $table . '`';
		list($indexes, $params) = $this->_generateIndexes( $indexes, 'WHERE', 'AND' );
		$query .= $indexes;
		
		if( $order !== null ) {
			$query .= ' ORDER BY ' . $order;
		}
		
		if( $start !== null ) {
			_a( is_int( $start ) );
			_a( is_int( $n ) ) ;
			$query .= ' LIMIT ' . $start . ', ' . $n;
		}

		$stmt = $this->_db->prepare( $query );
		$stmt->execute( $params );
		return $stmt;
	}
	
	public function get1( $table, $indexes ) {
		$stmt = $this->get( '*', $table, $indexes );
		_a( $stmt->rowCount() == 1 );
		return $stmt->fetch( \PDO::FETCH_ASSOC );
	}
	
	public function getN( $table, $indexes ) {
		$stmt = $this->get( '*', $table, $indexes );
		return $stmt->fetchAll( \PDO::FETCH_ASSOC );
	}
	
	public function getC( $table, $indexes ) {
		$stmt = $this->get( 'COUNT(*) AS n', $table, $indexes );
		$r = $stmt->fetch( \PDO::FETCH_ASSOC );
		return $r['n'];
	}
	
	public function getE( $table, $indexes, $order, $start = null, $n = null ) {
		$stmt = $this->get( '*', $table, $indexes, $order, $start, $n );
		return $stmt->fetchAll( \PDO::FETCH_ASSOC );
	}
	
	public function set1( $table, $indexes ) {
		$query = 'INSERT INTO `' . $table . '`';
		list($indexes, $params) = $this->_generateIndexes( $indexes, 'SET', ',' );
		$query .= $indexes;
		
		$stmt = $this->_db->prepare( $query );
		$stmt->execute( $params );
		return $this->_db->lastInsertId();
	}
	
	public function del( $table, $indexes ) {
		$query = 'DELETE FROM `' . $table . '`';
		list($indexes, $params) = $this->_generateIndexes( $indexes, 'WHERE', 'AND' );
		$query .= $indexes;
		
		$stmt = $this->_db->prepare( $query );

		$stmt->execute( $params );
	}
	
	public function upt( $table, $indexes, $where ) {
		$query = 'UPDATE `' . $table . '`';
		list($indexes, $params) = $this->_generateIndexes( $indexes, 'SET', ',' );
		list($indexes2, $params2) = $this->_generateIndexes( $where, 'WHERE', 'AND' );
		$query .= $indexes . $indexes2;
		
		$stmt = $this->_db->prepare( $query );

		$stmt->execute( $params + $params2 );
	}
	
	public function searchN( $table, $fields, $search ) {
		$query = 'SELECT * FROM `' . $table . '`';
		
		if( $fields ) {
			$key = array_shift( $fields );
			$query .= ' WHERE ' . $key . ' LIKE :value';
			foreach( $fields as $key ) {
				$query .= ' OR ' . $key . ' LIKE :value';
			}
		}
		
		$stmt = $this->_db->prepare( $query );
		$stmt->execute( array( ':value' => str_replace( '%', '\%', $search ) . '%' ) );

		return $stmt->fetchAll( \PDO::FETCH_ASSOC );
	}
	
	private function _generateIndexes( $indexes, $first, $sep ) {
		$query = '';
		$params = array();
		
		if( $indexes ) {
			$key = key($indexes);
			$value = array_shift( $indexes );
			$params[ ':' . $key ] = $value;
			$query .= ' ' . $first . ' `' . $key . '` = :' . $key;
		}
		
		foreach( $indexes as $key => $value ) {
			$params[ ':' . $key ] = $value;
			$query .= ' ' . $sep . ' `' . $key . '` = :' . $key;
		}
		return array( $query, $params );
	}
}
